from functools import partial
from exceptions import LiquidMissingFilterHandlerError
from utils import Registry, unpack_block, camel2snake, snake2camel


def has_filter_params(block):
    for i in block:
        if getattr(i, "data", None) == "filter_params":
            return True
    return False


def get_filter_params(block):
    params = []
    for i in block:
        if getattr(i, "data", None) == "filter_params":
            params.extend(i.children)
    return params


class FilterManager:
    __registry__ = Registry(custom_error=LiquidMissingFilterHandlerError)

    @classmethod
    def _get_filter_term(cls, child):
        """
        查找名字的优先级
        name属性 -> 类名除去Tag前缀
        """

        def _get_filter_term_from_clsname():
            import sys

            if sys.version_info.minor >= 9:
                return child.__name__.removeprefix("Filter")
            else:
                return child.__name__[len("Filter") :]

        return getattr(cls, "name", camel2snake(_get_filter_term_from_clsname()))

    def __init_subclass__(cls, **init_params):
        """
        直接将子类注册到父类下，
        这样可以避免使用register等装饰器去实现
        """

        # NOTE: 标签名，将被使用在parse过程中
        # NOTE: 使用这个名字作为词法树中的节点名,并且用于匹配。
        filter_term = FilterManager._get_filter_term(cls)

        # NOTE: 支持别名
        alias_names = init_params.get("alias", [])
        if isinstance(alias_names, str):
            alias_names = [alias_names]

        FilterManager.__registry__.add_handler(filter_term, alias_names, cls)

        return cls

    @classmethod
    def register(cls, *args, **kwargs):
        if "alias" in kwargs:
            alias = kwargs.get("alias")
            if isinstance(alias, str):
                alias_names = [alias]
            else:
                alias_names = alias

            def decorator(f):
                cls.__registry__.add_handler_func(f.__name__, alias_names, f)

            return decorator
        else:
            func = args[0]
            cls.__registry__.add_handler_func(func.__name__, [], func)

    @classmethod
    def get_filter(cls, term_or_alias):
        return getattr(cls.__registry__, term_or_alias).render
